iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 3
1

今天的重頭戲,正是逆向昨天剛寫好的 Hello world,從反方向觀察程式碼的長相。如果運用得宜,你可以更了解程式的具體行為。在生活中,逆向工程使用時機就好比,你看到一個 App 或程式、很想複製類似的功能,你可以嘗試逆逆看,看程式背後底在賣什麼膏藥。以工程界為例,香港有一位工程師因業餘興趣逆向 Facebook 的產品,透過社群平台比該公司更早流出官方未來產品走向,更在2018年的時候撼動股價!Reference

逆向指令

先用 file 指令來判斷檔案格式

在 terminal 中,下指令:
file helloworld
會得到結果:

重點在:Mach-O 64-bit executable x86_64
發現是一個可以執行在 Mac OS 的 x64 的檔案

使用 objdump 指令開始逆向

Wikipedia:
objdump 是在類 Unix 作業系統上顯示關於目的檔的各種資訊的命令行程式。例如,它可用作反組譯器來以組譯代碼形式檢視可執行檔。

在 terminal 中,下指令:
objdump -D helloworld
這裡的 helloworld 是 Day2 的時候所寫的程式,得到結果:

helloworld:	file format Mach-O 64-bit x86-64


Disassembly of section __TEXT,__text:

0000000100000f91 start:
100000f91: b8 04 00 00 02              	movl	$33554436, %eax
100000f96: bf 01 00 00 00              	movl	$1, %edi
100000f9b: 48 be 00 10 00 00 01 00 00 00       	movabsq	$4294971392, %rsi
100000fa5: ba 0e 00 00 00              	movl	$14, %edx
100000faa: 0f 05                       	syscall
100000fac: b8 01 00 00 02              	movl	$33554433, %eax
100000fb1: bf 00 00 00 00              	movl	$0, %edi
100000fb6: 0f 05                       	syscall

Disassembly of section __TEXT,__unwind_info:

0000000100000fb8 __unwind_info:
100000fb8: 01 00                       	addl	%eax, (%rax)
100000fba: 00 00                       	addb	%al, (%rax)
100000fbc: 1c 00                       	sbbb	$0, %al
100000fbe: 00 00                       	addb	%al, (%rax)
100000fc0: 00 00                       	addb	%al, (%rax)
100000fc2: 00 00                       	addb	%al, (%rax)
100000fc4: 1c 00                       	sbbb	$0, %al
100000fc6: 00 00                       	addb	%al, (%rax)
100000fc8: 00 00                       	addb	%al, (%rax)
100000fca: 00 00                       	addb	%al, (%rax)
100000fcc: 1c 00                       	sbbb	$0, %al
100000fce: 00 00                       	addb	%al, (%rax)
100000fd0: 02 00                       	addb	(%rax), %al
100000fd2: 00 00                       	addb	%al, (%rax)
100000fd4: 91                          	xchgl	%ecx, %eax
100000fd5: 0f 00 00                    	sldtw	(%rax)
100000fd8: 34 00                       	xorb	$0, %al
100000fda: 00 00                       	addb	%al, (%rax)
100000fdc: 34 00                       	xorb	$0, %al
100000fde: 00 00                       	addb	%al, (%rax)
100000fe0: b9 0f 00 00 00              	movl	$15, %ecx
100000fe5: 00 00                       	addb	%al, (%rax)
100000fe7: 00 34 00                    	addb	%dh, (%rax,%rax)
100000fea: 00 00                       	addb	%al, (%rax)
100000fec: 03 00                       	addl	(%rax), %eax
100000fee: 00 00                       	addb	%al, (%rax)
100000ff0: 0c 00                       	orb	$0, %al
100000ff2: 01 00                       	addl	%eax, (%rax)
100000ff4: 10 00                       	adcb	%al, (%rax)
100000ff6: 01 00                       	addl	%eax, (%rax)
		...

Disassembly of section __DATA,__data:

0000000100001000 msg:
100001000: 48 65                       	gs
100001002: 6c                          	insb	%dx, %es:(%rdi)
100001003: 6c                          	insb	%dx, %es:(%rdi)
100001004: 6f                          	outsl	(%rsi), %dx
100001005: 2c 20                       	subb	$32, %al
100001007: 77 6f                       	ja	111 <msg+0x78>
100001009: 72 6c                       	jb	108 <msg+0x77>
10000100b: 64 21 0a                    	andl	%ecx, %fs:(%rdx)

密密麻麻的,光看到這個顯示的語法就不想看了。於是,我們可以透過 -x86-asm-syntax 設定參數,將其轉換為比較好懂的 Intel 語法。

從AT&T轉成Intel語法

objdump -D -x86-asm-syntax=intel helloworld
使用 -D 來進行 disassemble(反組譯),透過 -x86-asm-syntax=intel,將其語法轉成 intel。接下來看下面的 code,不覺得清爽多了嗎XD

helloworld:	file format Mach-O 64-bit x86-64


Disassembly of section __TEXT,__text:

0000000100000f91 start:
100000f91: b8 04 00 00 02              	mov	eax, 33554436
100000f96: bf 01 00 00 00              	mov	edi, 1
100000f9b: 48 be 00 10 00 00 01 00 00 00       	movabs	rsi, 4294971392
100000fa5: ba 0e 00 00 00              	mov	edx, 14
100000faa: 0f 05                       	syscall
100000fac: b8 01 00 00 02              	mov	eax, 33554433
100000fb1: bf 00 00 00 00              	mov	edi, 0
100000fb6: 0f 05                       	syscall

Disassembly of section __TEXT,__unwind_info:

0000000100000fb8 __unwind_info:
100000fb8: 01 00                       	add	dword ptr [rax], eax
100000fba: 00 00                       	add	byte ptr [rax], al
100000fbc: 1c 00                       	sbb	al, 0
100000fbe: 00 00                       	add	byte ptr [rax], al
100000fc0: 00 00                       	add	byte ptr [rax], al
100000fc2: 00 00                       	add	byte ptr [rax], al
100000fc4: 1c 00                       	sbb	al, 0
100000fc6: 00 00                       	add	byte ptr [rax], al
100000fc8: 00 00                       	add	byte ptr [rax], al
100000fca: 00 00                       	add	byte ptr [rax], al
100000fcc: 1c 00                       	sbb	al, 0
100000fce: 00 00                       	add	byte ptr [rax], al
100000fd0: 02 00                       	add	al, byte ptr [rax]
100000fd2: 00 00                       	add	byte ptr [rax], al
100000fd4: 91                          	xchg	eax, ecx
100000fd5: 0f 00 00                    	sldt	word ptr [rax]
100000fd8: 34 00                       	xor	al, 0
100000fda: 00 00                       	add	byte ptr [rax], al
100000fdc: 34 00                       	xor	al, 0
100000fde: 00 00                       	add	byte ptr [rax], al
100000fe0: b9 0f 00 00 00              	mov	ecx, 15
100000fe5: 00 00                       	add	byte ptr [rax], al
100000fe7: 00 34 00                    	add	byte ptr [rax + rax], dh
100000fea: 00 00                       	add	byte ptr [rax], al
100000fec: 03 00                       	add	eax, dword ptr [rax]
100000fee: 00 00                       	add	byte ptr [rax], al
100000ff0: 0c 00                       	or	al, 0
100000ff2: 01 00                       	add	dword ptr [rax], eax
100000ff4: 10 00                       	adc	byte ptr [rax], al
100000ff6: 01 00                       	add	dword ptr [rax], eax
		...

Disassembly of section __DATA,__data:

0000000100001000 msg:
100001000: 48 65                       	gs
100001002: 6c                          	insb	byte ptr es:[rdi], dx
100001003: 6c                          	insb	byte ptr es:[rdi], dx
100001004: 6f                          	outsd	dx, dword ptr [rsi]
100001005: 2c 20                       	sub	al, 32
100001007: 77 6f                       	ja	111 <msg+0x78>
100001009: 72 6c                       	jb	108 <msg+0x77>
10000100b: 64 21 0a                    	and	dword ptr fs:[rdx], ecx

反組譯的解讀

稍稍說明一下各分區(Section)的用途。第18行的 section __TEXT,__unwind_info主要是用來回溯資料資訊結構是用來記錄函式對堆疊指標的影響。簡單來說,主要作為Debug使用,我們先不用理會。接著,我們來看第4行的 section __TEXT,__text,他是分析時的重要入口。仔細觀察後,不難發現,它與我們在 Day2 寫的 code 架構是大致相同的(比方說,第7~14行都是先 mov,再 syscall,再接著 mov,最後再 syscall)。主要差別就在於後面的數字變了,至於為什麼會變,牽扯到16進位轉換成10進位的問題,之後會再討論。接著看第51行的 section __DATA,__data,用來儲存 helloworld 資料(無法直接從程式碼看到資料,只能看到他如何儲存資料)。

所以,透過 objdump 指令,我們可以發現一件事。就算沒有 source code (原本的程式碼),我們也可以透過逆向的方式來大致了解該程式的運行邏輯。

結論

有了一些逆向的經驗後,明天會接續說明組合語言的分段(Section),重點在電腦是如何儲存程式碼的片段!


上一篇
Day2 - 寫程式的濫觴 - 用組合語言寫 Hello world!
下一篇
Day4 - 程式碼如何分段?
系列文
逆向工程 – 從入門到放棄30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言